package com.tjing.frame.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.thoughtworks.xstream.XStream;
import com.tjing.bussiness.model.*;
import com.tjing.bussiness.services.MemberDwr;
import com.tjing.bussiness.support.MessagePush;
import com.tjing.frame.model.Dic;
import com.tjing.frame.object.ClassInfo;
import com.tjing.frame.object.RequestObject;
import com.tjing.frame.object.ResponseObject;
import com.tjing.frame.services.DataCache;
import com.tjing.frame.services.DataPerfect;
import com.tjing.frame.services.DbServices;
import com.tjing.frame.services.XMLUtil;
import com.tjing.frame.util.CodeHelper;
import common.tool;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import util.Constants;

import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.security.KeyStore;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;

@Controller
@RequestMapping(value="/public/tool")
public class ToolController {
	@Autowired
	private  HttpServletRequest request;
	private  HttpServletResponse response;
	@Autowired
	private DataPerfect dataperfect;
	@Autowired
	private DbServices dbServices;
	@Autowired
	private MessagePush messagePush;
	@Autowired
	DataCache dataCache;

	@Autowired
	MemberDwr memberDwr;

	@ModelAttribute
	public void setResponse(HttpServletResponse response){
		this.response = response;
	}

	@RequestMapping(value="/gendicjs")
	public ResponseEntity<List<Dic>> genDicJs(@RequestParam(value="data[]") String[] data){
		Map<String, Dic> dicGroupMap = dataCache.getDicsFromCache();
		List<Dic> dics = Lists.newLinkedList();
		for(String p : data){
			Dic dic = dicGroupMap.get(p);
			if(dic!=null) {
				dics.add(dic);
			}
		}
		ResponseEntity<List<Dic>> responseEntity = new ResponseEntity<List<Dic>>(dics,HttpStatus.OK);
		return responseEntity;
	}
	@RequestMapping(value="/saveOrUpdateRecords")
	public ResponseEntity<ResponseObject> saveOrUpdateRecords(RequestObject requestObject){
		ResponseObject res = new ResponseObject();
		String methodName = requestObject.getMethod();
		if(StringUtils.isNotEmpty(methodName)){
			try {
				MethodUtils.invokeMethod(dataperfect, methodName, new Object[]{requestObject});
			} catch (NoSuchMethodException | IllegalAccessException
					| InvocationTargetException e) {
				e.printStackTrace();
			}
			if(!requestObject.isPromise()){
				ResponseEntity<ResponseObject> responseEntity = new ResponseEntity<ResponseObject>(res,HttpStatus.OK);
				if(StringUtils.isNotEmpty(requestObject.getMessage())){
					res.setMessage(requestObject.getMessage());
				}
				return responseEntity;
			}
		}

		String returnId = dbServices.saveOrupdateRecords(requestObject.getPoName(), requestObject.getData(), requestObject.getMethod(), requestObject.iscreate());
		res.setMessage("保存成功");
		if(requestObject!=null){
			res.setId(returnId);
			res.setRecordNum(requestObject.getData().size());
		}
		ResponseEntity<ResponseObject> responseEntity = new ResponseEntity<ResponseObject>(res,HttpStatus.OK);
		return responseEntity;
	}
	@RequestMapping(value="/deleteRecords")
	public ResponseEntity<ResponseObject> deleteRecords(RequestObject requestObject){
		ResponseObject res = new ResponseObject();
		String methodName = requestObject.getMethod();
		if(StringUtils.isNotEmpty(methodName)){
			try {
				MethodUtils.invokeMethod(dataperfect, methodName, new Object[]{requestObject});
			} catch (NoSuchMethodException | IllegalAccessException
					| InvocationTargetException e) {
				e.printStackTrace();
			}
			if(!requestObject.isPromise()){
				ResponseEntity<ResponseObject> responseEntity = new ResponseEntity<ResponseObject>(res,HttpStatus.OK);
				if(StringUtils.isNotEmpty(requestObject.getMessage())){
					res.setMessage(requestObject.getMessage());
				}
				return responseEntity;
			}
		}

		List<String> idlist = requestObject.getArr();
		ClassInfo classInfo = CodeHelper.getClassInfo(requestObject.getPoName());
		int deleteNum = 0;
		if(classInfo.getIdType().equals("Integer")){
			List<Integer> ids = Lists.newArrayList();
			for(String id : idlist){
				ids.add(Integer.valueOf(id));
			}
			deleteNum = dbServices.deleteByIds(requestObject.getPoName(),ids);
		}else{
			//ID为字符串
		}
		if(requestObject!=null){
			res.setId(requestObject.getId());
			res.setRecordNum(deleteNum);
		}
		ResponseEntity<ResponseObject> responseEntity = new ResponseEntity<ResponseObject>(res,HttpStatus.OK);
		return responseEntity;
	}

	@RequestMapping(value="/loadFormData")
	public ResponseEntity<JSONObject> loadFormData(RequestObject requestObject) throws ClassNotFoundException {
		ClassInfo classInfo = CodeHelper.getClassInfo(requestObject.getPoName());
		Class<?> clazzObj = Class.forName(classInfo.getFullName());
		JSONObject jobj = null;
		if(StringUtils.isEmpty(requestObject.getId())){
			jobj = new JSONObject();
		}else{
			Object entity = dbServices.getEntity(clazzObj, Integer.valueOf(requestObject.getId()));
			jobj = JSON.parseObject(JSON.toJSONString(entity));
		}
		ResponseEntity<JSONObject> responseEntity = new ResponseEntity<JSONObject>(jobj,HttpStatus.OK);
		return responseEntity;
	}

	@RequestMapping(value="/uploadimg")
	public @ResponseBody Map uploadimg(RequestObject requestObject) throws Exception{
		Map resultMap = new HashMap();
		JSONObject jobUploadImg = new JSONObject();
		jobUploadImg.put("img", uploads(request, response,true));

		resultMap.put("state", "1");
		resultMap.put("msg", "ok");
		resultMap.put("data", jobUploadImg);
		return resultMap;
	}

	@RequestMapping(value="/uploadFile")
	public @ResponseBody Map uploadFile(RequestObject requestObject) throws Exception{
		Map resultMap = new HashMap();
		JSONObject jobUploadImg = new JSONObject();
		jobUploadImg.put("img", uploads(request, response,false));

		resultMap.put("state", "1");
		resultMap.put("msg", "ok");
		resultMap.put("data", jobUploadImg);
		return resultMap;
	}

	//生成流水号
	public static String GetOrderId()
	{
		Date nowTime=new Date();
		SimpleDateFormat time=new SimpleDateFormat("yyyyMMddHHmmss");
		String code = "";
		for (int i = 0; i < 3; i++) {
			code +=(int)(Math.random()*10);
		}
		return time.format(nowTime) + code;
	}
	/// <summary>
	/// 生成随机数任意位
	/// </summary>
	/// <param name="length"></param>
	/// <returns></returns>
	public static String GetRandNumString(int length)
	{
		StringBuilder MyStringBuilder = new StringBuilder();
		java.util.Random r=new java.util.Random();
		for(int i=0;i<length;i++){
			MyStringBuilder.append(r.nextInt());
		}
		return MyStringBuilder.toString();
	}
	/// <summary>
	/// 生成随机字母任意位
	/// </summary>
	/// <param name="length"></param>
	/// <returns></returns>
	public static String GetRandLetterString(int length)
	{
		StringBuilder MyStringBuilder = new StringBuilder();
		char[] A_Z = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R'
				,'S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m'
				,'n','o','p','q','r','s','t','u','v','w','x','y','z'};
		Random rd = new Random();
		for(int i=0;i<20;i++)//随即10个拿出来看看
		{
			MyStringBuilder.append(A_Z[rd.nextInt(52)]);
		}
		return MyStringBuilder.toString();
	}

	public static String GetRandNum(int length)
	{
		StringBuilder MyStringBuilder = new StringBuilder();
		char[] A_Z = {'0','1','2','3','4','5','6','7','8','9'};
		Random rd = new Random();
		for(int i=0;i<length;i++)//随即10个拿出来看看
		{
			MyStringBuilder.append(A_Z[rd.nextInt(10)]);
		}
		return MyStringBuilder.toString();
	}

	private String uploads(HttpServletRequest request,HttpServletResponse response,boolean isPic){
		//得到上传文件的保存目录，将上传的文件存放于WEB-INF目录下，不允许外界直接访问，保证上传文件的安全
		String savePath = request.getSession().getServletContext().getRealPath("/upload");
		//上传时生成的临时文件保存目录
		String tempPath =request.getSession().getServletContext().getRealPath("/temp");
		File tmpFile = new File(tempPath);
		if (!tmpFile.exists()) {
			//创建临时目录
			tmpFile.mkdir();
		}
		//消息提示
		String message = "";
		try{
			//使用Apache文件上传组件处理文件上传步骤：
			//1、创建一个DiskFileItemFactory工厂
			DiskFileItemFactory factory = new DiskFileItemFactory();
			//设置工厂的缓冲区的大小，当上传的文件大小超过缓冲区的大小时，就会生成一个临时文件存放到指定的临时目录当中。
			factory.setSizeThreshold(1024*100);//设置缓冲区的大小为100KB，如果不指定，那么缓冲区的大小默认是10KB
			//设置上传时生成的临时文件的保存目录
			factory.setRepository(tmpFile);
			//2、创建一个文件上传解析器
			ServletFileUpload upload = new ServletFileUpload(factory);
			//监听文件上传进度
			upload.setProgressListener(new ProgressListener(){
				public void update(long pBytesRead, long pContentLength, int arg2) {
					System.out.println("文件大小为：" + pContentLength + ",当前已处理：" + pBytesRead);
					/**
					 * 文件大小为：14608,当前已处理：4096
					 文件大小为：14608,当前已处理：7367
					 文件大小为：14608,当前已处理：11419
					 文件大小为：14608,当前已处理：14608
					 */
					float f = pBytesRead/pContentLength;

				}
			});
			//解决上传文件名的中文乱码
			upload.setHeaderEncoding("UTF-8");
			//3、判断提交上来的数据是否是上传表单的数据
			if(!ServletFileUpload.isMultipartContent(request)){
				//按照传统方式获取数据
				return "";
			}

			//设置上传单个文件的大小的最大值，目前是设置为1024*1024字节，也就是1MB
			upload.setFileSizeMax(1024*1024*100);
			//设置上传文件总量的最大值，最大值=同时上传的多个文件的大小的最大值的和，目前设置为10MB
			upload.setSizeMax(1024*1024*100);
			//4、使用ServletFileUpload解析器解析上传数据，解析结果返回的是一个List<FileItem>集合，每一个FileItem对应一个Form表单的输入项
			List<FileItem> list = upload.parseRequest(request);
			for(FileItem item : list){
				//如果fileitem中封装的是普通输入项的数据
				if(item.isFormField()){
					String name = item.getFieldName();
					//解决普通输入项的数据的中文乱码问题
					String value = item.getString("UTF-8");
					//value = new String(value.getBytes("iso8859-1"),"UTF-8");
					System.out.println(name + "=" + value);
				}else{//如果fileitem中封装的是上传文件
					//得到上传的文件名称，
					String filename = item.getName();
					System.out.println(filename);
					if(filename==null || filename.trim().equals("")){
						continue;
					}
					//注意：不同的浏览器提交的文件名是不一样的，有些浏览器提交上来的文件名是带有路径的，如：  c:\a\b\1.txt，而有些只是单纯的文件名，如：1.txt
					//处理获取到的上传文件的文件名的路径部分，只保留文件名部分
					filename = filename.substring(filename.lastIndexOf(System.getProperty("file.separator"))+1);
					//得到上传文件的扩展名
					String fileExtName = filename.substring(filename.lastIndexOf(".")+1);

					//如果需要限制上传的文件类型，那么可以通过文件的扩展名来判断上传的文件类型是否合法
					System.out.println("上传的文件的扩展名是："+fileExtName);
					//获取item中的上传文件的输入流
					InputStream in = item.getInputStream();
					//得到文件保存的名称
					String saveFilename = makeFileName(filename);

					//得到文件的保存目录
					String realSavePath = makePath(saveFilename, savePath);
					System.out.println(realSavePath);
					//创建一个文件输出流
					FileOutputStream out = new FileOutputStream(realSavePath +System.getProperty("file.separator") + saveFilename);

					//创建一个缓冲区
					byte buffer[] = new byte[1024];
					//判断输入流中的数据是否已经读完的标识
					int len = 0;
					//循环将输入流读入到缓冲区当中，(len=in.read(buffer))>0就表示in里面还有数据
					while((len=in.read(buffer))>0){
						//使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中
						out.write(buffer, 0, len);
					}
					//关闭输入流
					in.close();
					//关闭输出流
					out.close();
					//删除处理文件上传时生成的临时文件
					item.delete();
					message = "文件上传成功！";
					StringBuffer url = request.getRequestURL();
					String tempContextUrl = url.delete(url.length() - request.getRequestURI().length(), url.length()).append(request.getContextPath()).append("/").toString();
					if(isPic) {
						String smallFilename="s_"+saveFilename;
						tool.CutZoomImage(realSavePath + System.getProperty("file.separator") + saveFilename, request.getRealPath("/upload/" + smallFilename), 300, 300, fileExtName);

					}
					return tempContextUrl+"upload/" + saveFilename;
				}
			}
		}catch (FileUploadBase.FileSizeLimitExceededException e) {
			e.printStackTrace();
			request.setAttribute("message", "单个文件超出最大值！！！");

			return "";
		}catch (FileUploadBase.SizeLimitExceededException e) {
			e.printStackTrace();
			request.setAttribute("message", "上传文件的总的大小超出限制的最大值！！！");

			return "";
		}catch (Exception e) {
			message= "文件上传失败！";
			e.printStackTrace();
		}
		request.setAttribute("message",message);

		return "";
	}
	/**
	 * @Method: makeFileName
	 * @Description: 生成上传文件的文件名，文件名以：uuid+"_"+文件的原始名称
	 * @Anthor:孤傲苍狼
	 * @param filename 文件的原始名称
	 * @return uuid+"_"+文件的原始名称
	 */
	private String makeFileName(String filename){  //2.jpg
		//为防止文件覆盖的现象发生，要为上传文件产生一个唯一的文件名
		return UUID.randomUUID().toString() + "_" + filename;
	}

	/**
	 * 为防止一个目录下面出现太多文件，要使用hash算法打散存储
	 * @Method: makePath
	 * @Description:
	 * @Anthor:孤傲苍狼
	 *
	 * @param filename 文件名，要根据文件名生成存储目录
	 * @param savePath 文件存储路径
	 * @return 新的存储目录
	 */
	private String makePath(String filename,String savePath){
		//得到文件名的hashCode的值，得到的就是filename这个字符串对象在内存中的地址
		int hashcode = filename.hashCode();
		int dir1 = hashcode&0xf;  //0--15
		int dir2 = (hashcode&0xf0)>>4;  //0-15
		//构造新的保存目录
		String dir = savePath + "\\" + dir1 + "\\" + dir2;  //upload\2\3  upload\3\5
		//File既可以代表文件也可以代表目录
		File file = new File(savePath);
		//如果目录不存在
		if(!file.exists()){
			//创建目录
			file.mkdirs();
		}
		return savePath;
	}
	public static void sendMsg(String content,String mobile){
		System.out.println("极光推送"+mobile);
		tool.sendGet("http://push.360uut.com", "m=" + tool.getURLEncoderString(content) + "&k=3caab81b0948411a8e9bbddb&p=f4e501e9bb5ae19de567f543&t=" + mobile);
	}

	//增加或减少天数
	public static Date addDay(Date date, int num) {
		Calendar startDT = Calendar.getInstance();
		startDT.setTime(date);
		startDT.add(Calendar.DAY_OF_MONTH, num);
		return startDT.getTime();
	}

	public void addCommission() {
		Map resultMap = new HashMap();
		HashMap<Integer, Object> intParamMap = new HashMap<Integer, Object>();
		String hql="";
		int i = 0;
		Date nowTime=new Date();
		SimpleDateFormat time=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String strnowTime= time.format(nowTime);

		List<JSONObject> jsonObjects = Lists.newArrayList();
		JSONObject jsonObject = new JSONObject();

		QhSysPar qhSysPar=dbServices.getEntity(QhSysPar.class, 1);

		SimpleDateFormat fmtTime=new SimpleDateFormat("yyyy-MM-dd");
		Date date= ToolController.addDay(new Date(), -1);
		String strDate=fmtTime.format(date);

		intParamMap.clear();
		hql="from QhSysParLeave";
		List<QhSysParLeave> qhSysParLeaves = dbServices.findListByHql(hql, intParamMap);

		hql="from QhUser";
		List<QhUser> qhUsers = dbServices.findListByHql(hql, intParamMap);
		for(QhUser qhUser:qhUsers){
			hql = "select sum(CashMoney) from qh_user_profit where CreateUser=? and DATE_FORMAT(CreateDateTime,'%Y-%m-%d')=? and type='分享' and taskid not in (select taskid from qh_task_share where CreateUserLeave=1 and CreateUser=?)";
			i = 0;
			intParamMap.clear();
			intParamMap.put(i++, qhUser.getMobile());
			intParamMap.put(i++, "2017-09-30");
			intParamMap.put(i++, qhUser.getMobile());
			Object Omoney1 = dbServices.findUniqueBySql(hql, intParamMap);

			hql = "select sum(CashMoney) from qh_user_profit where CreateUser=? and DATE_FORMAT(CreateDateTime,'%Y-%m-%d')=? and type='下载' ";
			i = 0;
			intParamMap.clear();
			intParamMap.put(i++, qhUser.getMobile());
			intParamMap.put(i++, "2017-09-30");
			Object Omoney2 = dbServices.findUniqueBySql(hql, intParamMap);

			hql = "select sum(CashMoney) from qh_user_profit where CreateUser=? and DATE_FORMAT(CreateDateTime,'%Y-%m-%d')=? and type='阅读' ";
			Object Omoney3 = dbServices.findUniqueBySql(hql, intParamMap);

			Double cashMoney1=Omoney1==null?0.0:Double.valueOf(Omoney1.toString());
			Double cashMoney2=Omoney2==null?0.0:Double.valueOf(Omoney2.toString());
			Double cashMoney3=Omoney3==null?0.0:Double.valueOf(Omoney3.toString());
			Double cashMoney=cashMoney1+cashMoney2*qhSysPar.getDownloadPer()+cashMoney3;

			if(cashMoney==0){
				continue;
			}

			String inviter=qhUser.getInviter();

			for(Integer y=0;y<9;y++){
				if(inviter==null||inviter.equals("")){
					break;
				}
				i=0;
				intParamMap.clear();
				intParamMap.put(i++, inviter);
				hql="from QhUser where mobile=?";
				List<QhUser> qhUsers1 = dbServices.findListByHql(hql, intParamMap);
				if(qhUsers1.size()>0){
					inviter=qhUsers1.get(0).getInviter();

					if(qhUsers1.get(0).getLeav()!=1&&qhUsers1.get(0).getLeav()>y+1) {
						jsonObject.put("uid", qhUsers1.get(0).getId());

						Double per=0.0;
						switch (y){
							case 0:
								per=qhSysParLeaves.get(1).getUsePer();
								break;
							case 1:
								per=qhSysParLeaves.get(2).getUsePer();
								break;
							case 2:
								per=qhSysParLeaves.get(3).getUsePer();
								break;
							case 3:
								per=qhSysParLeaves.get(4).getUsePer();
								break;
							case 4:
								per=qhSysParLeaves.get(5).getUsePer();
								break;
							case 5:
								per=qhSysParLeaves.get(6).getUsePer();
								break;
							case 6:
								per=qhSysParLeaves.get(7).getUsePer();
								break;
							case 7:
								per=qhSysParLeaves.get(8).getUsePer();
								break;
							case 8:
								per=0.0;
								break;
							default:
								per=0.0;
								break;
						}

						jsonObject.put("cashMoney", cashMoney * per);
						jsonObject.put("note", "");
						jsonObject.put("createUser", qhUser.getMobile());
						jsonObject.put("createDateTime", strnowTime);
						jsonObject.put("modifyUser", qhUser.getMobile());
						jsonObject.put("modifyDateTime", strnowTime);
						jsonObject.put("state", 99);
						jsonObjects.clear();
						jsonObjects.add(jsonObject);
						dbServices.saveOrupdateRecords("QhUserCommission", jsonObjects, null, false);

						jsonObject.clear();
						jsonObject.put("taskId", 0);
						jsonObject.put("type", "学徒");
						jsonObject.put("cashMoney", cashMoney * per);
						jsonObject.put("note", "");
						jsonObject.put("createUser", qhUsers1.get(0).getMobile());
						jsonObject.put("createDateTime", strnowTime);
						jsonObject.put("modifyUser", qhUsers1.get(0).getMobile());
						jsonObject.put("modifyDateTime", strnowTime);
						jsonObject.put("state", 99);
						jsonObjects.clear();
						jsonObjects.add(jsonObject);
						dbServices.saveOrupdateRecords("QhUserProfit", jsonObjects, null, false);

						QhUser qhUser1=dbServices.getEntity(QhUser.class,qhUsers1.get(0).getId());
						double TotalFund=qhUser1.getTotalFund() + cashMoney* per;
						double AvailFund=qhUser1.getAvailFund() + cashMoney* per;
						qhUser1.setTotalFund(TotalFund);
						qhUser1.setAvailFund(AvailFund);
						dbServices.update(qhUser1);
					}
				}
			}
		}
		i=0;
		intParamMap.clear();
		intParamMap.put(i++, 0);
		hql="from QhTask where state=?";
		List<QhTask> qhTasks = dbServices.findListByHql(hql, intParamMap);
		for(QhTask qhTask:qhTasks){
			qhTask.setState(1);
			dbServices.update(qhTask);
		}
	}
	//判断是否整数
	public static boolean isInteger(String str) {
		Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
		return pattern.matcher(str).matches();
	}
}
